#if !defined(BISTREAM_H)
#define BISTREAM_H

#include <istream>
#include <string>
#include <vector>
#include <list>
#include "biotypes.h"

namespace xtd {

template<class E, class Tr = std::char_traits<E> >
	class basic_bistream : public std::basic_istream<E, Tr> {
	typedef basic_bistream<E, Tr> bistream;
public:
// construction/destruction
    explicit basic_bistream(std::basic_streambuf<E, Tr> * buf) : std::basic_istream<E, Tr>(buf) {};
    virtual ~basic_bistream() {};
// inserters
    template <class T> bistream & get(T & x) {
		const int REM = sizeof(T) % sizeof(E);	// remainder
        const int SIZE = sizeof(T) / sizeof(E) + (REM ? 1 : 0); // ceil
/*#if !defined __GNUC__ && !defined __BORLANDC__
		if (REM) {
			union { T value; E bytes[SIZE]; } u;		
			read(u.bytes, SIZE);
			x = u.value; // copying!
		} else {
#endif
*/ 			read(reinterpret_cast<E *>(& x), SIZE);
/*#if !defined __GNUC__ && !defined __BORLANDC__
		}
#endif
*/        return * this;
    } 
    bistream & operator >> (bool & x)
        { return get(x); }
    bistream & operator >> (signed short int & x)
        { return get(x); }
    bistream & operator >> (unsigned short int & x)
        { return get(x); }
    bistream & operator >> (signed int & x)          
        { return get(x); }
    bistream & operator >> (unsigned int & x)          
        { return get(x); }
    bistream & operator >> (signed long int & x)     
        { return get(x); }
    bistream & operator >> (unsigned long int & x)     
        { return get(x); }
    bistream & operator >> (signed char & x)
        { return get(x); }
    bistream & operator >> (unsigned char & x)         
        { return get(x); }
    bistream & operator >> (float & x) 
        { return get(x); }
    bistream & operator >> (double & x) 
        { return get(x); }
    bistream & operator >> (long double & x) 
        { return get(x); }
    bistream & operator >> (void * & x) 
        { return get(x); }
};
             
typedef basic_bistream<char, std::char_traits<char> > bistream;

inline bistream & operator >> (bistream & in, std::string & x) { 
	int32u len;
	in >> len;
	x.resize(len);
	in.read(const_cast<char *>(x.c_str()), len);
	return in;
}

inline bistream & operator >> (bistream & in, const char * x) { 
	std::string s;
	in >> s;
	if (s != x)
		in.setstate(std::ios::failbit);
	return in;
}

template <class T>
bistream & operator >> (bistream & in, std::vector<T> & x) {
	int32u len;
	in >> len;
	x.resize(len);
	typename std::vector<T>::iterator i;
	for (i = x.begin(); i != x.end(); ++i)
		in >> *i;
	return in;
}

template <class T>
bistream & operator >> (bistream & in, std::list<T> & x) {
	int32u len;
	in >> len;
	x.clear();
	for (; len > 0; --len) {
		T t;
		in >> t;
		x.push_back(t);
	}
	return in;
}

} // xtd

#endif // !defined(BOSTREAM_H)
